package br.com.foxinline.util;

import br.com.foxinline.modelo.Anexo;
import java.io.*;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import net.coobird.thumbnailator.name.Rename;

/**
 *
 * @author laverson
 */
public class ArquivoUtilitario {

    public static final String REAL_PATH_TMP = "/tmp/Atlas/uploads/";
    public static final String REAL_PATH_OPT = "/opt/Atlas/uploads/";
    private static final String THUMBNAIL = "thumbnail";

    public ArquivoUtilitario() {
    }

    /**
     *
     * Adiciona um anexo a lista de anexos do processo que está sendo adicionado a lista de processos do protocolo
     *
     * @param event
     * @throws FileNotFoundException
     * @throws SQLException
     * @throws IOException
     */
    public Anexo adicionarArquivo(byte[] bytes, String fileName, String contentType) throws FileNotFoundException, SQLException, IOException {
        try {
            Anexo anexo = new Anexo();

            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
            String data = dateFormat.format(new Date());

            String nomeExibicao = fileName.replace("/", " ");
            String nomeReal = data + nomeExibicao;

            anexo.setNome(nomeReal);

            // Aqui cria o diretorio caso não exista
            File file = new File(REAL_PATH_TMP);
            file.mkdirs();

            byte[] arquivo = bytes;
            String caminho = REAL_PATH_TMP + nomeReal.trim();

            gravarArquivo(caminho, arquivo);
            if (!getFileSuffix(nomeReal).equals("pdf")) {
                criarMiniatura(caminho);
            }

            anexo.setUrl(REAL_PATH_TMP);
            anexo.setArquivo(arquivo);
            anexo.setNomeExibicao(nomeExibicao);
            anexo.setTipo(contentType);

            return anexo;
        } catch (Exception ex) {
            Msg.messagemError("Erro ao Copiar Arquivo para Anexo");
            return null;
        }
    }

    /**
     *
     * Grava os anexos no diretório "/opt/uploads/"
     *
     * @param anexos, lista de anexos a serem gravados
     */
    public void gravarAnexos(List<Anexo> anexos) {

        if (anexos != null && !anexos.isEmpty()) {
            for (Anexo a : anexos) {
                if (a.getId() == null) {
                    gravarAnexo(a);
                }
            }
        }
    }

    /**
     *
     * Grava o 'arquivo' no diretório informado pela 'url'
     *
     * @param caminho caminho onde o arquivo vai ser gravado
     * @param arquivo arquivo a ser gravado no 'caminho'
     * @throws FileNotFoundException
     * @throws IOException
     */
    public void gravarArquivo(String caminho, byte[] arquivo) throws FileNotFoundException, IOException {
        // esse trecho grava o arquivo no diretório
        FileOutputStream fos = new FileOutputStream(caminho);
        fos.write(arquivo);
        fos.close();
    }

    /**
     *
     * Exclui o arquivo do diretório
     *
     * @param f Arquivo a ser removido
     * @return true, se removido com sucesso, false caso contrário
     * @throws FileNotFoundException
     */
    public boolean excluirArquivo(File f) throws FileNotFoundException {
        try {
            String caminhoImagemMiniatura = f.getPath().replace(f.getName(), "");
            caminhoImagemMiniatura += THUMBNAIL + "." + f.getName();

            File fThumb = new File(caminhoImagemMiniatura);

            //converte o objeto file em array de bytes
            List<InputStream> inputStreams = new ArrayList<InputStream>();
            inputStreams.add(new FileInputStream(f.getPath()));
            if (fThumb.exists()) {
                inputStreams.add(new FileInputStream(caminhoImagemMiniatura));
            }

            for (InputStream inputStream : inputStreams) {
                byte[] bytes = new byte[(int) f.length()];
                int offset = 0;
                int numRead = 0;
                while (offset < bytes.length && (numRead = inputStream.read(bytes, offset, bytes.length - offset)) >= 0) {
                    offset += numRead;
                }
                inputStream.close();
            }

            if (fThumb.exists()) {
                fThumb.delete();
            }
            f.delete(); //Deleta o arquivo onde foi criado

            return true;

        } catch (IOException ex) {

            System.err.println(ex);
        }
        return false;
    }

    public void excluirArquivos(List<Anexo> anexos) {
        for (Anexo anexo : anexos) {
            try {
                excluirArquivo(new File(anexo.getUrl() + anexo.getNome()));
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    /**
     *
     * Cria uma miniatura da imagem existente no caminho informado
     *
     * @param caminhoImagem Caminho completo da imagem Ex: ../imagens/icon.png
     */
    public static void criarMiniatura(String caminhoImagem) {
        try {
            Thumbnails.of(new File(caminhoImagem)).crop(Positions.CENTER).size(60, 60).toFiles(Rename.PREFIX_DOT_THUMBNAIL);
        } catch (IOException ex) {
            System.err.println(ex);
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Seta os bytes dos arquivos como null
     *
     * @param anexos Lista dos anexos que serão modificados
     * @return anexos com os bytes removidos
     */
    public List<Anexo> removerBytes(List<Anexo> anexos) {
        if (anexos != null && !anexos.isEmpty()) {

            for (Anexo anexo : anexos) {
                if (anexo.getId() == null) {
                    removerBytes(anexo);
                }
            }
        }

        return anexos;
    }

    public void removerBytes(Anexo anexo) {
        anexo.setArquivo(null);
    }

    public void gravarAnexo(Anexo a) {
        String oldPath = a.getUrl().concat(a.getNome());

        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
            String data = dateFormat.format(new Date());

            String nomeArquivo = Caracter.removeCaracterIgnoraPonto(a.getNome());
            nomeArquivo = Caracter.removerAcentos(nomeArquivo);
            nomeArquivo = Caracter.substituirEspacos(nomeArquivo);

            a.setNome(data + nomeArquivo);
            a.setUrl(REAL_PATH_OPT);

            gravarArquivo(a.getUrl() + a.getNome(), a.getArquivo());
            criarMiniatura(a.getUrl().concat(a.getNome()));

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }

        try {
            excluirArquivo(new File(oldPath));
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public Anexo gravarAnexoCopia(Anexo a) {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
            String data = dateFormat.format(new Date());

            String ext = "";
            int index = a.getNome().lastIndexOf(".");

            if (index != -1) {
                ext = a.getNome().substring(index, a.getNome().length());
                if (ext.length() > 4) {
                    ext = "";
                }
            }
            String nomeArquivo = Caracter.removeCaracterIgnoraPonto(a.getNomeExibicao().concat(ext));

            nomeArquivo = Caracter.removerAcentos(nomeArquivo);
            nomeArquivo = Caracter.substituirEspacos(nomeArquivo);

            a.setNome(data + nomeArquivo);
            a.setUrl(REAL_PATH_OPT);

            gravarArquivo(a.getUrl() + a.getNome(), a.getArquivo());
            criarMiniatura(a.getUrl().concat(a.getNome()));

            return a;

        } catch (FileNotFoundException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
        }

        return a;
    }

    /**
     *
     * Grava os anexos no diretório "/opt/uploads/"
     *
     * @param anexos, lista de anexos a serem gravados
     */
    public void gravarAnexos(List<Anexo> anexos, String url) {

        criarDiretorio(url);

        if (anexos != null && !anexos.isEmpty()) {
            for (Anexo a : anexos) {
//                if (a.getId() == null) {
                gravarAnexo(a, url);
//                }
            }
        }
    }

    public void criarDiretorio(String caminho) {
        try {
            if (!new File(caminho).exists()) { // Verifica se o diretório existe.   
                (new File(caminho)).mkdirs();   // Cria o diretório   
            }
        } catch (Exception ex) {
            System.err.println("Erro ao criar diretorio. " + ArquivoUtilitario.class.getSimpleName() + "\n "
                    + "Metodo: criaDiretorio(String novoDiretorio)");
            System.err.println(ex);
        }
    }

    public void gravarAnexo(Anexo a, String url) {

        File file = new File(url);

        if (!file.exists()) {
            file.mkdirs();
        }

        if (a != null && a.getArquivo() != null) {

            if (a.getNome() == null || a.getNome().isEmpty()) {

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.err.println(e);
                }

                SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss-SSSS");
                String data = dateFormat.format(new Date());

                a.setNome(data + ".jpg");
            }

            String oldPath = a.getUrl().concat(a.getNome());

            try {
                a.setUrl(url);

                gravarArquivo(a.getUrl() + a.getNome(), a.getArquivo());
                if (!getFileSuffix(a.getNome()).equals("pdf")) {
                    criarMiniatura(a.getUrl().concat(a.getNome()));
                }

            } catch (FileNotFoundException ex) {
                Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
            }

            try {
                if (!oldPath.equals(a.getUrl() + a.getNome())) {
                    excluirArquivo(new File(oldPath));
                }
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ArquivoUtilitario.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public static String getFileSuffix(final String path) {
        String result = null;
        if (path != null) {
            result = "";
            if (path.lastIndexOf('.') != -1) {
                result = path.substring(path.lastIndexOf('.'));
                if (result.startsWith(".")) {
                    result = result.substring(1);
                }
            }
        }
        return result;
    }
}
